import { Injectable, Logger } from '@nestjs/common';
import * as puppeteer from 'puppeteer';
import {
  ICrawler,
  NovelInfo,
  ChapterInfo,
  ChapterContent,
} from '../interfaces/crawler.interface';

export interface QidianChapterInfo {
  title: string;
  url: string;
  index: number;
  isFree: boolean;
  content?: string;
  volumeName: string;
}

@Injectable()
export class QidianCrawler implements ICrawler {
  private readonly logger = new Logger(QidianCrawler.name);
  private browser: puppeteer.Browser;

  async initBrowser() {
    if (!this.browser) {
      const executablePath =
        process.env.CHROME_EXECUTABLE_PATH ||
        'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe';

      this.browser = await puppeteer.launch({
        headless: true,
        executablePath,
        args: [
          '--no-sandbox',
          '--disable-setuid-sandbox',
          '--disable-web-security',
        ],
      });
    }
  }

  getSource(): string {
    return 'qidian';
  }

  validateUrl(url: string): boolean {
    return url.includes('qidian.com');
  }

  async getNovelInfo(url: string): Promise<NovelInfo> {
    await this.initBrowser();
    const page = await this.browser.newPage();

    try {
      // 设置更真实的用户代理
      await page.setUserAgent(
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
      );

      // 设置视窗大小
      await page.setViewport({ width: 1920, height: 1080 });

      this.logger.log(`开始访问起点页面: ${url}`);

      // 先访问页面，等待基础加载
      await page.goto(url, {
        waitUntil: 'domcontentloaded',
        timeout: 30000,
      });

      // 等待页面内容加载
      await new Promise((resolve) => setTimeout(resolve, 5000));

      // 获取页面基本信息，先检查是否成功加载
      const pageTitle = await page.title();
      this.logger.log(`页面标题: ${pageTitle}`);

      // 尝试多种选择器来获取小说信息
      const novelInfo = await page.evaluate(() => {
        // 定义选择器集合
        const selectors = {
          title: [
            '.book-info__title',
            'h1.book-name',
            '.book-name',
            'h1',
            '.title',
            '[class*="title"]',
            '.lib-name',
            '.main-title',
            '.text-info-title h1',
            '.detail-wrap h1',
          ],
          author: [
            '.book-info__author__name',
            '.author',
            '.book-author',
            '[class*="author"]',
            '.writer',
            '.author-name',
            '.text-info-author a',
            '.detail-wrap .author',
          ],
          cover: [
            '.book-img__img',
            '.book-cover img',
            '.book-img img',
            '.cover img',
            'img[src*="cover"]',
            '.book-cover-pic img',
          ],
          category: [
            '.book-info__tag',
            '.tag',
            '[class*="category"]',
            '.book-category',
            '.text-info-category',
          ],
          description: [
            '.book-info__intro',
            '.description',
            '.intro',
            '[class*="intro"]',
            '.book-desc',
            '.book-intro',
            '.text-info-desc',
          ],
        };

        // 通用的元素查找函数
        function findElement(selectors: string[]): Element | null {
          for (const selector of selectors) {
            const element = document.querySelector(selector);
            if (element && element.textContent?.trim()) {
              return element;
            }
          }
          return null;
        }

        // 获取文本内容
        function getText(selectors: string[]): string {
          const element = findElement(selectors);
          if (!element) return '';

          let text = element.textContent?.trim() || '';

          // 清理常见的前缀
          text = text.replace(/^书名[:：]\s*/, '');
          text = text.replace(/^作者[:：]\s*/, '');
          text = text.replace(/^简介[:：]\s*/, '');

          return text;
        }

        // 获取属性值
        function getAttribute(selectors: string[], attr: string): string {
          const element = findElement(selectors);
          if (!element) return '';

          return (
            element.getAttribute(attr) ||
            element.getAttribute(`data-${attr}`) ||
            ''
          );
        }

        // 提取小说基本信息
        const title = getText(selectors.title);
        const author = getText(selectors.author);
        const cover = getAttribute(selectors.cover, 'src');
        const category = getText(selectors.category);
        const description = getText(selectors.description);

        // 从页面各个位置提取状态、字数、更新时间等信息
        let status = 0;
        let wordCount = '';
        let updateTime = '';

        // 查找包含状态、字数、更新时间的元素
        const infoElements = document.querySelectorAll(
          '.book-info__row, .book-info-detail, .detail-wrap, .text-info-item, .info-item',
        );
        infoElements.forEach((element) => {
          const text = element.textContent?.trim() || '';

          if (text.includes('完结') || text.includes('连载')) {
            status = text.includes('完结') ? 1 : 0;
          }

          if (text.includes('万字') || text.includes('字')) {
            wordCount = text;
          }

          if (text.match(/\d{4}-\d{2}-\d{2}/) || text.includes('更新')) {
            updateTime = text;
          }
        });

        // 章节列表暂时为空，稍后单独获取
        return {
          title,
          author,
          cover,
          description,
          category,
          wordCount,
          status,
          updateTime,
          chapterList: [],
        };
      });

      // 尝试获取章节列表 - 通过构造目录URL或查找目录链接
      let chapters: ChapterInfo[] = [];

      // 从URL提取书籍ID
      const bookIdMatch = url.match(/\/(\d+)/);
      if (bookIdMatch) {
        const bookId = bookIdMatch[1];
        const catalogUrl = `https://www.qidian.com/book/${bookId}/catalog`;

        this.logger.log(`尝试访问目录页面: ${catalogUrl}`);

        try {
          await page.goto(catalogUrl, { waitUntil: 'domcontentloaded' });
          await new Promise((resolve) => setTimeout(resolve, 3000));

          // 在目录页面解析章节
          chapters = await page.evaluate(() => {
            const chapterList: ChapterInfo[] = [];

            // 查找卷和章节
            const volumeElements = document.querySelectorAll(
              '.volume-wrap, .volume, .cf, [class*="volume"]',
            );

            volumeElements.forEach((volumeElement, volumeIndex) => {
              const volumeName =
                volumeElement
                  .querySelector(
                    '.volume-name, .vol-name, [class*="volume-name"]',
                  )
                  ?.textContent?.trim() || `第${volumeIndex + 1}卷`;

              // 在卷内查找章节
              const chapterElements = volumeElement.querySelectorAll(
                '.chapter-item, .cf li, a[href*="/chapter/"], [class*="chapter"]',
              );

              chapterElements.forEach((chapterElement, chapterIndex) => {
                const linkElement =
                  chapterElement.querySelector('a') || chapterElement;
                const title = linkElement?.textContent?.trim() || '';
                const href = linkElement?.getAttribute('href') || '';

                if (title && href) {
                  const fullUrl = href.startsWith('http')
                    ? href
                    : `https://www.qidian.com${href}`;
                  chapterList.push({
                    title,
                    url: fullUrl,
                    index: chapterList.length + 1,
                  });
                }
              });
            });

            // 如果没有找到卷结构，尝试直接查找章节
            if (chapterList.length === 0) {
              const directChapters = document.querySelectorAll(
                'a[href*="/chapter/"], .chapter-item',
              );
              directChapters.forEach((element, index) => {
                const title = element.textContent?.trim() || '';
                const href = element.getAttribute('href') || '';

                if (title && href) {
                  const fullUrl = href.startsWith('http')
                    ? href
                    : `https://www.qidian.com${href}`;
                  chapterList.push({
                    title,
                    url: fullUrl,
                    index: index + 1,
                  });
                }
              });
            }

            return chapterList;
          });

          this.logger.log(`从目录页面获取到 ${chapters.length} 个章节`);
        } catch (error) {
          this.logger.warn(`访问目录页面失败: ${error.message}`);
        }
      }

      // 创建新的NovelInfo对象，避免readonly属性的问题
      const finalNovelInfo: NovelInfo = {
        ...novelInfo,
        chapterList: chapters.slice(0, 50), // 限制章节数量
      };

      this.logger.log(
        `起点小说解析完成: 标题="${finalNovelInfo.title}", 作者="${finalNovelInfo.author}", 章节数=${finalNovelInfo.chapterList.length}`,
      );
      return finalNovelInfo;
    } catch (error) {
      this.logger.error(`解析起点小说失败: ${error.message}`, error.stack);
      throw new Error(`解析起点小说失败: ${error.message}`);
    } finally {
      await page.close();
    }
  }

  async getChapterContent(chapterUrl: string): Promise<ChapterContent> {
    await this.initBrowser();
    const page = await this.browser.newPage();

    try {
      await page.setUserAgent(
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
      );
      await page.setViewport({ width: 1920, height: 1080 });
      await page.goto(chapterUrl, { waitUntil: 'domcontentloaded' });

      await new Promise((resolve) => setTimeout(resolve, 3000));

      const chapterContent = await page.evaluate(() => {
        const title =
          document
            .querySelector('.chapter-title, h1, .title')
            ?.textContent?.trim() || '';

        const contentElement =
          document.querySelector(
            '.chapter-content, .content, [class*="content"]',
          ) || document.querySelector('.text-content, .read-content');

        let content = contentElement?.textContent?.trim() || '';

        const isVip =
          document.querySelector('.vip-content, .vip-tip, [class*="vip"]') !==
          null;

        if (isVip) {
          content = '【VIP章节，需要付费订阅才能阅读完整内容】';
        }

        return {
          title,
          content,
          index: 0,
        };
      });

      return chapterContent;
    } finally {
      await page.close();
    }
  }

  /**
   * 获取详细的章节信息，包括收费状态和内容
   */
  async getDetailedChapterList(
    catalogUrl: string,
  ): Promise<QidianChapterInfo[]> {
    await this.initBrowser();
    const page = await this.browser.newPage();

    try {
      await page.setUserAgent(
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
      );
      await page.goto(catalogUrl, { waitUntil: 'domcontentloaded' });

      const chapters = await page.evaluate(() => {
        const chapterList: QidianChapterInfo[] = [];
        const volumeElements = document.querySelectorAll(
          '[class*="volume"], .volume-wrap, .volume',
        );

        volumeElements.forEach((volumeElement, volumeIndex) => {
          const volumeName =
            volumeElement
              .querySelector('.volume-name, [class*="volume-name"]')
              ?.textContent?.trim() || `第${volumeIndex + 1}卷`;

          const chapterElements = volumeElement.querySelectorAll(
            '[class*="chapter"], .chapter-item, a[href*="chapter"]',
          );

          chapterElements.forEach((chapterElement, chapterIndex) => {
            const linkElement =
              chapterElement.querySelector('a') || chapterElement;
            const title = linkElement?.textContent?.trim() || '';
            const href =
              linkElement?.getAttribute('href') ||
              chapterElement?.getAttribute('href') ||
              '';

            const isFree =
              !chapterElement.querySelector(
                '[class*="vip"], [class*="lock"], .vip-icon, .lock',
              ) &&
              !title.includes('VIP') &&
              !title.includes('付费');

            if (title && href) {
              const fullUrl = href.startsWith('http')
                ? href
                : `https://www.qidian.com${href}`;
              chapterList.push({
                title,
                url: fullUrl,
                index: chapterList.length + 1,
                isFree,
                volumeName,
                content: undefined,
              });
            }
          });
        });

        return chapterList;
      });

      // 为免费章节获取内容
      for (const chapter of chapters) {
        if (chapter.isFree) {
          try {
            const chapterContent = await this.getChapterContent(chapter.url);
            chapter.content = chapterContent.content;
            this.logger.log(`获取免费章节内容: ${chapter.title}`);

            await new Promise((resolve) => setTimeout(resolve, 1000));
          } catch (error) {
            this.logger.warn(
              `获取章节内容失败: ${chapter.title}, ${error.message}`,
            );
            chapter.content = '获取内容失败';
          }
        }
      }

      return chapters;
    } finally {
      await page.close();
    }
  }

  async onModuleDestroy() {
    if (this.browser) {
      await this.browser.close();
    }
  }
}
